using System;
using System.Collections.Generic;
using System.Text;

namespace NCommet.Core.Agents
{
    /// <summary>
    /// MatchingStringConditions is an enumeration that is used when checking if a string is contained inside another string.    
    /// </summary>
    public enum MatchingStringConditions
    {
        STARTS_WITH,
        CONTAINS,
        ENDS_WITH
    }

    /// <summary>
    /// IPersisterMetadata provides information about the persister.
    /// </summary>
    public interface IPersisterMetadata
    {
        /// <summary>
        /// Returns the maximum length of an item's name.
        /// </summary>
        /// <returns>The maximum length of an item's name.</returns>
        int GetItemNameMaxLength();
    }

    /// <summary>
    /// IPersister handles the persistence of everything related to an item (item, content,
    /// related items, tags).
    /// </summary>
    public interface IPersister
    {
        /// <summary>
        /// Gets an object from persistence.
        /// </summary>
        /// <typeparam name="T">The type of the object to find and return.</typeparam>
        /// <param name="ItemID">The id of the object.</param>
        /// <returns>The object with the specified <paramref name="ItemID"/></returns>
        T Get<T>(int ItemID);

        /// <summary>
        /// Saves the given object to persistence. If there is no open transaction, the save operation
        /// is performed in its own implicit transaction.
        /// </summary>
        /// <param name="item">The item to be saved.</param>
        void Save(object item);

        /// <summary>
        /// Begins a transaction.
        /// </summary>
        void BeginTransaction();

        /// <summary>
        /// Commits the active transaction.
        /// </summary>
        void CommitTransaction();

        /// <summary>
        /// Rollbacks the active transaction.
        /// </summary>
        void RollbackTransaction();

        /// <summary>
        /// Deletes the given object from persistence. If there is no open transaction, the delete operation
        /// is performed in its own implicit transaction.
        /// </summary>
        /// <param name="item">The item to be deleted.</param>
        void Delete(object item);

        /// <summary>
        /// Returns all the root items, i.e. all items with <c>null</c> parent.
        /// </summary>
        /// <returns>A list of <see cref="NCommet.Core.Item"/></returns>
        IList<Item> GetRoots();

        /// <summary>
        /// Returns all the root items of the specified item type.
        /// </summary>
        /// <param name="ItemType">The specified item type.</param>
        /// <returns>A list of <see cref="NCommet.Core.Item"/></returns>
        IList<Item> GetRoots(string ItemType);

        /// <summary>
        /// Returns all the root items whose item type is included in the specified array.
        /// </summary>
        /// <param name="ItemTypes">The array of item types.</param>
        /// <returns>A list of <see cref="NCommet.Core.Item"/></returns>
        IList<Item> GetRoots(string[] ItemTypes);

        /// <summary>
        /// Gets the relItems that have the specified item as a relative.
        /// </summary>
        /// <param name="relative">The specified item.</param>
        /// <returns>A list of <see cref="NCommet.Core.RelItem"/></returns>
        IList<RelItem> GetReverseRelItems(Item relative);

        /// <summary>
        /// Deletes relItems of the specified item.
        /// </summary>
        /// <param name="item">The item whose relations are to be deleted.</param>
        /// <param name="relationType">If not null, delete relations of this relation type.</param>
        /// <param name="participatesAsSubject">If true, deletes relations where the given item participates as subject (owner).</param>
        /// <param name="participatesAsObject">If true, deletes relations where the given item participates as object (relative).</param>
        void DeleteRelItems(Item item, string relationType, bool participatesAsSubject, bool participatesAsObject);

        /// <summary>
        /// Deletes relItems of the specified item and of its children.
        /// </summary>
        /// <param name="item">The item whose relations are to be deleted.</param>
        /// <param name="relationType">If not null, delete relations of this relation type.</param>
        /// <param name="participatesAsSubject">If true, deletes relations where the given item participates as subject (owner).</param>
        /// <param name="participatesAsObject">If true, deletes relations where the given item participates as object (relative).</param>
        void DeleteRelItemsRecursive(Item item, string relationType, bool participatesAsSubject, bool participatesAsObject);

        /// <summary>
        /// Filters children of the given item, returning those whose item type equals the specified item type.
        /// </summary>
        /// <param name="parent">The item whose children are filtered.</param>
        /// <param name="ItemType">The specified item type.</param>
        /// <returns>A list of <see cref="NCommet.Core.Item"/></returns>
        IList<Item> FilterChildren(Item parent, string ItemType);

        /// <summary>
        /// Filters children of the given item on item type and tags.
        /// </summary>
        /// <param name="parent">The item whose children are filtered.</param>
        /// <param name="ItemTypes">If not null, returns items whose item type is included in this array.</param>
        /// <param name="Tags">If not null, returns items whose at least one tag is included in this array.</param>
        /// <returns>A list of <see cref="NCommet.Core.Item"/></returns>
        IList<Item> FilterChildren(Item parent, string[] ItemTypes, string[] Tags);

        /// <summary>
        /// Filters children of the given item, returning those whose item type is included in the given parameter.
        /// </summary>
        /// <param name="parent">The item whose children are filtered.</param>
        /// <param name="ItemTypes">If not null, returns items whose item type is included in this enumeration.</param>
        /// <returns>A list of <see cref="NCommet.Core.Item"/></returns>
        IList<Item> FilterChildren(Item parent, IEnumerable<string> ItemTypes);

        /// <summary>
        /// Filters relItems owned by the given item. Relations where the item acts as relative are not returned.
        /// </summary>
        /// <param name="parent">The item whose relItems are returned.</param>
        /// <param name="RelationType">If not null, returns only those relItems whose relation type is equal to this parameter.</param>
        /// <param name="RelativeItemType">If not null, returns only relItems whose relative item type equals this parameter.</param>
        /// <returns></returns>
        IList<RelItem> FilterRelItems(Item parent, string RelationType, string RelativeItemType);

        /// <summary>
        /// Checks if the given object has been initialized from persistence.
        /// </summary>
        /// <param name="proxy">The given object.</param>
        /// <returns>True, if the given object has been initialized from persistence.</returns>
        bool IsInitialized(object proxy);

        /// <summary>
        /// Returns all items that are persisted.
        /// </summary>
        /// <returns>A list of <see cref="NCommet.Core.Item"/> that are persisted.</returns>
        IList<Item> GetAllItems();

        /// <summary>
        /// Returns all items that have the specified name.
        /// </summary>
        /// <param name="Name">The specified name.</param>
        /// <returns>A list of <see cref="NCommet.Core.Item"/> that have the specified name.</returns>
        IList<Item> GetItemsByName(string Name);

        /// <summary>
        /// Returns all items of the specified item type. A LIKE comparison is performed.
        /// </summary>
        /// <param name="ItemType">The specified item type.</param>
        /// <returns>A list of <see cref="NCommet.Core.Item"/> that have the specified item type.</returns>
        IList<Item> GetItemsByItemType(string ItemType);

        /// <summary>
        /// Returns all items with a content, which contains a field that starts with, contains or ends with a specified string.
        /// </summary>
        /// <param name="ItemType">The type of the items that are checked. If it is null, every item type is returned.</param>
        /// <param name="FieldName">The field of the item's content that is being checked.</param>
        /// <param name="InputString">The string that is being checked if it's contained in the <paramref name="FieldName"/> 
        /// according to the specified criteria.</param>
        /// <param name="condition">The condition that the <paramref name="InputString"/> should fullfill.</param>        
        /// <returns>A list of <see cref="NCommet.Core.Item"/></returns>
        IList<Item> GetItemsByContent(string ItemType, string FieldName, string InputString, MatchingStringConditions condition);

        /// <summary>
        /// Returns the number of items that have the specified name.
        /// </summary>
        /// <param name="Name">The specified name.</param>
        /// <returns>The number of items that have the specified name.</returns>
        int GetItemCountByName(string Name);

        /// <summary>
        /// Checks if the given item is transient (not persisted).
        /// </summary>
        /// <param name="item">The given item.</param>
        /// <returns>True, if the <paramref name="item"/> is transient.</returns>
        bool IsTransient(Item item);

        /// <summary>
        /// Checks if the given content object is transient (not persisted).
        /// </summary>
        /// <param name="contentBase">The given content object.</param>
        /// <returns>True, if the <paramref name="contentBase"/> is transient.</returns>
        bool IsTransient(ContentBase contentBase);

        /// <summary>
        /// Gets the persister's metadata object.
        /// </summary>
        /// <returns>The <see cref="IPersisterMetadata"/></returns>
        IPersisterMetadata GetPersisterMetadata();

        /// <summary>
        /// Requests a new session from the persister.
        /// </summary>
        void RequestExplicitSession();

        /// <summary>
        /// Returns the item ids of the children of the item with the specified id.
        /// </summary>
        /// <param name="ParentId">The specified id of the parent item.</param>
        /// <returns>The ids of the children items.</returns>
        IList<int> SelectIds(int ParentId);

        /// <summary>
        /// Returns the items that have the specified item ids.
        /// </summary>
        /// <param name="Ids">A list of the specified item ids.</param>
        /// <returns>A list of <see cref="NCommet.Core.Item"/></returns>
        IList<Item> GetItems(IList<int> Ids);
    }
}
